import pygame

import queue as qe
import my.neural_network as neural_network
import my.aigame_config as config
import numpy as np

'''
game()类
'''

pygame.init()


class Cake(object):
    BTM_IMG = pygame.image.load("./res/blank.png")
    # TOP_IMG = pygame.transform.rotate(BTM_IMG, 180)

    WIDTH = BTM_IMG.get_width() - 32  # surface的宽度
    HEIGHT = BTM_IMG.get_height() - 32   # surface的高度

    cakeXVY = [600 - 48, 0 - 64, 3, -4]  # 记录初始位置和初始速度

    def __init__(self, network, surface, cakeXVY):
        self.x = cakeXVY[0]
        self.y = cakeXVY[1]
        self.x_mov = cakeXVY[2]
        self.y_mov = cakeXVY[3]
        self.g = 0.04
        # 点击之后的横纵加速度
        self.y_g = 0
        self.cut = False
        self.collis = False
        self.alive = True
        self.surface = surface
        self.neural_netwoek = network

    def draw(self, surface):
        # if self.alive:
        surface.blit(Cake.BTM_IMG, (self.x, self.y))

    def update(self, caketower):
        self.x -= self.x_mov
        self.y -= self.y_mov
        self.y_mov += self.g
        # 正常移动
        if self.x > Game.SIZE[0]:
            self.x_mov = -self.x_mov
            self.y_mov = -self.y_mov

        # 反向移动
        # if self.x < -Cake.WIDTH+100:
        if self.x <= 0 - 16 or self.x >= Game.SIZE[0] - 48:
            self.x_mov = -self.x_mov
            self.y_mov = -self.y_mov
        # 点击下落
        if self.cut:
            # 抛物线
            # -------------------横轴
            # 横轴速度不变
            # -------------------纵轴
            self.y_mov += self.y_g
            self.y_g += -0.01

        if self.y > Game.SIZE[1]:
            self.alive = False

        inputs = self.get_inputs(caketower)
        result = self.neural_netwoek.getResult(inputs)
        print(result)
        if result[0] > 0.5:
            self.cut_line()

    # 剪短连接线
    def cut_line(self):
        self.cut = True


    def collision(self, caketower):

        #if caketower.top_l + 32 >= self.x + 16 >= caketower.top_l - 32:
        if Game.SIZE[0]/2 + 32 >= self.x + 16 >= Game.SIZE[0]/2 - 32:

            if self.y >= Game.SIZE[1] - 32 * 5 - 48:
                caketower.click = True
                self.collis = True
                return True
            else:
                return False
        else:
            return False

    def draw_line(self):
        if not self.cut:
            pygame.draw.line(self.surface,
                             (122, 122, 255),
                             (self.x + 32, self.y + 14),
                             (Game.SIZE[0] / 2, 0), 2)  # 画辅助线

    def get_inputs(self, caketower):
        inputs = []
        # 初始化输入数据
        for _ in range(config.network[0]):
            inputs.append(0.0)
        if caketower.top_l + 32 <= self.x + 16:  # >= caketower.top_l - 32:
            inputs[0] = self.y / Game.SIZE[1]
            inputs[1] = (self.x + Cake.WIDTH) - caketower.top_l
            inputs[2] = self.x - (caketower.top_l + Cake.WIDTH)
            inputs[3] = self.y - 32 * 5
            inputs[4] = (self.y + Cake.HEIGHT) - Game.SIZE[1]
        return inputs


class CakeTower(object):
    BTM_IMG = pygame.image.load("./res/cake3.png")  # 画布大小64*64

    # TOP_IMG = pygame.transform.rotate(BTM_IMG, 180)

    def __init__(self, surface):
        self.que = qe.Queue()
        # self.cakes = []
        self.index = 5
        self.surface = surface

        self.x = Game.SIZE[0] / 2 - 32
        self.y = Game.SIZE[1] - 16
        self.x_mov = 1
        self.y_mov = 1
        self.click = False
        self.count = 0
        self.top_l = 0
        self.score = 0

    # 初始化caketower
    def tower_init(self):
        for i in range(self.index):
            cakexyv = [self.x, self.y - 32 * (i + 1), 0, 0]
            cake = Cake(None, self.surface, cakexyv)
            self.que.put(cake)

    def draw(self):
        for i in range(self.que.qsize()):
            cak = self.que.get()  # 取出cake用于展示
            cak.draw(self.surface)
            # 同时记录此时塔顶蛋糕的左坐标
            if i == 4:
                self.top_l = cak.x + 16
            self.que.put(cak)  # 重新放入queue

        # for i in range(self.index):
        #     self.surface.blit(CakeTower.BTM_IMG, (self.x, self.y-32*(i+1)))
        #     #print(self.y-32*(i+1))

    def update(self):

        while self.click and self.count < 32:
            self.count += 1
            for i in range(self.que.qsize()):
                cak = self.que.get()  # 取出cake用于展示
                cak.y += 1
                cak.draw(self.surface)
                self.que.put(cak)  # 重新放入queue
            # self.count += 1
            if self.count == 1:
                self.score += 1
                print("score")
                print(self.score)
        else:
            self.click = False
            self.count = 0


class Score(object):

    def __init__(self):
        self.score = 0
        self.all_imgs = []
        for i in range(10):
            img = pygame.image.load("./res/"+str(i)+".png")
            self.all_imgs.append(img)
        self.x = 0
        self.y = 30
        self.imgs = []

    def draw(self, surface):
        pre_width = 0
        for img in self.imgs:
            pre_width = img.get_width()
            surface.blit(img, (self.x, self.y))
            self.x += pre_width
            print(pre_width)


    def update(self):
        self.imgs.clear()
        index = self.SplitScore()
        for i in index:
            self.imgs.append(self.all_imgs[i])
        width = 0
        for img in self.imgs:
            width += img.get_width()
        self.x = Game.SIZE[0]/2-width/2

    def SplitScore(self):
        index_list = []
        i = 1
        score = self.score
        while True:
            ret = score % 10
            index_list.insert(0, ret)
            score = int(self.score / 10 ** i)
            if score == 0:
                break
            i += 1
        return tuple(index_list)  # 打包成列表


class Game(object):
    SIZE = (600, 480)
    FPS = 50 * 3

    # PIPE_GAP_SIZE = 80 # 管道间隙
    def __init__(self):
        # 不需要重置的属性
        self.surface = pygame.display.set_mode((600, 480))
        self.clock = pygame.time.Clock()

        self.game_init()

    def game_init(self):
        # 游戏开始后需要更新的属性
        self.time = 0
        self.gameRunning = True
        self.cakexyv = [0, 0, 0, 0]

        weight_array = np.loadtxt("./res/my_modle.csv")
        network = neural_network.NeuralNetwork(config.network[0], config.network[1], config.network[2])
        data = network.getNetwork()
        if len(data['weights']) == len(weight_array):
            for i in range(len(data['weights'])):
                data['weights'][i] = weight_array[i]
        network.setNetwork(data)

        self.cake = Cake(network, self.surface, Cake.cakeXVY)
        self.score = Score()
        self.caketower = CakeTower(self.surface)
        self.caketower.tower_init()  # 对tower 进行初始化\

        self.time = 0
        self.gameRunning = True
        self.cakexyv = [0, 0, 0, 0]

    def control(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.stop()
            # if event.type == pygame.KEYDOWN:
            #     if event.key == pygame.K_SPACE:
            #         self.cake.cut_line()
            #         self.cakexyv[0] = self.cake.x
            #         self.cakexyv[1] = self.cake.y
            #         self.cakexyv[2] = self.cake.x_mov
            #         self.cakexyv[3] = self.cake.y_mov

    def draw(self):
        # 绘制背景
        self.surface.fill((169, 169, 160))
        self.cake.draw_line()  # 保证效果，先画辅助线
        self.cake.draw(self.surface)  # 画蛋糕
        self.caketower.draw()  # 画蛋糕塔
        self.score.draw(self.surface)

    def update(self):
        self.caketower.click = self.cake.collision(self.caketower)

        if self.caketower.click:
            self.cake.y = 304 - 32
            self.caketower.que.put(self.cake)  # 将cake添加入队列
            self.caketower.update()  # 先进性添加在进行更新
            self.caketower.que.get()

            # 开始下一个蛋糕
            self.cake = Cake(self.surface, self.cakexyv)

        # self.caketower.update()
        if not self.cake.alive:
            del self.cake  # 清除对象
            #self.cake = Cake(self.surface)  # 重新创建
            self.game_init()
        self.cake.update(self.caketower)
        self.score.score = self.caketower.score
        self.score.update()


    '''
    start
    '''

    def start(self):
        while self.gameRunning:
            self.control()
            self.update()
            self.draw()
            pygame.display.update()

            # 计算游戏时间
            self.time += self.clock.tick(self.FPS)

    '''
    stop
    '''

    def stop(self):
        self.gameRunning = False

    '''
    restart
    '''

    def restart(self):
        self.game_init()


if __name__ == "__main__":
    game = Game()
    game.start()